MODULE fmm_global_types

   IMPLICIT NONE
   PUBLIC   

!------------------------------------------------------------------------------

   ! We select here the REAL and INTEGER precisions
   !   INTEGER, PARAMETER :: fmm_INTK  = SELECTED_INT_KIND(9),           &
   !                         fmm_REALK = SELECTED_REAL_KIND(XXX) 
   ! Use standard integers and REAL*8 double precision floats
   INTEGER, PARAMETER :: fmm_INTK  = KIND(1),                         &
                         fmm_REALK = KIND(1D0) 

!===============================================================================
! Derived types |
!================

    ! Structure for defining boundary planes (assuming // to axes)
   TYPE fmm_planes
      REAL(fmm_REALK) :: xmin,xmax, ymin,ymax, zmin,zmax
   END TYPE fmm_planes

!------------------------------------------------------------------------------

   TYPE LHS_RHS_type 
      INTEGER(fmm_INTK) :: LHS, RHS
   END TYPE LHS_RHS_type

!------------------------------------------------------------------------------

   TYPE fmm_range
      INTEGER(fmm_INTK) :: hi, lo, tot
   END TYPE fmm_range
 
!------------------------------------------------------------------------------

    ! Complete prescription of FMM execution held in "scheme"
   TYPE T_contract_schm 
      INTEGER(fmm_INTK) :: NF_ID, FF_ID
      INTEGER(fmm_INTK) :: NF_T_buffer, FF_T_buffer
      INTEGER(fmm_INTK) :: NF_sort_para, FF_sort_para
      INTEGER(fmm_INTK) :: LHS_mm_type, RHS_mm_type 
   END TYPE T_contract_schm 

   TYPE W_contract_schm 
      INTEGER(fmm_INTK) :: ID         ! general translator
      INTEGER(fmm_INTK) :: BR_ID      ! box-to-raw translator
      INTEGER(fmm_INTK) :: W_buffer
      INTEGER(fmm_INTK) :: sort_para
   END TYPE W_contract_schm 

   TYPE fmm_scheme
      INTEGER(fmm_INTK)     :: job_type
      LOGICAL               :: include_near_field
      INTEGER(fmm_INTK)     :: algorithm, phase
      INTEGER               :: NF_T_searcher, FF_T_searcher
      TYPE(T_contract_schm) :: T_con
      TYPE(W_contract_schm) :: W_con
      LOGICAL               :: branch_free
      INTEGER(fmm_INTK)     :: raw_lmax, trans_lmax
      INTEGER(fmm_INTK)     :: LHS_mm_range, RHS_mm_range 
      LOGICAL               :: pack_LHS, pack_RHS
      LOGICAL               :: LHS_dens, RHS_dens
      REAL(fmm_REALK)       :: extent_min 
      REAL(fmm_REALK)       :: grain
      REAL(fmm_REALK)       :: dens_screen_thr
   END TYPE fmm_scheme
 
!------------------------------------------------------------------------------

    ! Raw (not boxed) multipole moment data structure
   TYPE raw_mm_paras
      REAL(fmm_REALK)   :: cntr(3), ext
      INTEGER(fmm_INTK) :: batch            ! batch id of unique centres/extents
      INTEGER(fmm_INTK) :: id               ! map to raw moments array
      INTEGER(fmm_INTK) :: map_up           ! map to boxed multipole moment
      INTEGER(fmm_INTK) :: box(3), bra
      REAL(fmm_REALK)   :: box_cntr(3)
   END TYPE raw_mm_paras

   TYPE J_index_type
      INTEGER(fmm_INTK) :: i_indx, j_indx   ! map to J_matrix elements
   END TYPE J_index_type

   TYPE raw_mm_data 
      TYPE(raw_mm_paras), POINTER :: paras(:)
      REAL(fmm_REALK),    POINTER :: dens(:)  
      REAL(fmm_REALK),    POINTER :: qlm(:,:)  
      REAL(fmm_REALK),    POINTER :: qlm_T(:,:)  
      REAL(fmm_REALK),    POINTER :: qlm_W(:,:)  
      TYPE(J_index_type), POINTER :: J_indices(:)
      TYPE(id_list),      POINTER :: batch_map(:) ! maps raw paras in one batch
   END TYPE raw_mm_data 
 
!------------------------------------------------------------------------------

    ! Boxed multipole moment data structure
   TYPE box_mm_paras
      INTEGER(fmm_INTK) :: box(3)
      REAL(fmm_REALK)   :: cntr(3)
      INTEGER(fmm_INTK) :: bra, level
      INTEGER(fmm_INTK) :: map_up            ! map to moment at next level 
      REAL(fmm_REALK)   :: cntr_up(3)        ! centre of parent box
      INTEGER(fmm_INTK) :: id                ! map to moment at this level
   END TYPE box_mm_paras
   TYPE box_mm_data
      TYPE(box_mm_paras), POINTER :: LHS_paras(:)
      TYPE(box_mm_paras), POINTER :: RHS_paras(:)
      ! Just RHS moments (only RHS is built up in box hierarchy)
      REAL(fmm_REALK),    POINTER :: qlm_T(:,:)  
      REAL(fmm_REALK),    POINTER :: qlm_W(:,:)  
   END TYPE box_mm_data
 
!------------------------------------------------------------------------------

    ! Map structure to link packed parameters with all raw moment members
   TYPE id_node
      INTEGER(fmm_INTK) :: id
      INTEGER(fmm_INTK) :: i_indx, j_indx
      TYPE(id_node), POINTER :: next
   END TYPE id_node

   TYPE id_list
      INTEGER(fmm_INTK) :: occ 
      TYPE(id_node), POINTER :: head
   END TYPE id_list

!------------------------------------------------------------------------------

    ! Generalised multipole moment parameter structure
   TYPE gen_mm_paras
      TYPE(raw_mm_paras), POINTER :: raw_paras(:)
      TYPE(box_mm_paras), POINTER :: box_paras(:)
   END TYPE gen_mm_paras
 
!------------------------------------------------------------------------------

   TYPE T_paras
      INTEGER(fmm_INTK) :: LHS_lmax, LHS_id
      INTEGER(fmm_INTK) :: RHS_lmax, RHS_id
      INTEGER(fmm_INTK) :: weight
      REAL(fmm_REALK)   :: ratio
   END TYPE T_paras

   TYPE T_pair_single
      TYPE(T_paras)     :: paras
      REAL(fmm_REALK)   :: r_ab(3)
      INTEGER(fmm_INTK) :: lmax, lm_max
      ! Used only for W_pairs when translating to distinguish qlm and Vff modes
      CHARACTER(1)      :: N_or_T
   END TYPE T_pair_single

   TYPE T_pair_list
      TYPE(T_paras), POINTER :: paras(:) 
      REAL(fmm_REALK)        :: r_ab(3)
      INTEGER(fmm_INTK)      :: lmax, lm_max
      INTEGER(fmm_INTK)      :: LHS_lmax, RHS_lmax
      ! Used only for W_pairs when translating to distinguish qlm and Vff modes
      CHARACTER(1)           :: N_or_T
   END TYPE T_pair_list

   TYPE T_pair_batch
      TYPE(T_pair_single), POINTER :: items(:)
      INTEGER(fmm_INTK) :: ndim
   END TYPE T_pair_batch
 
    ! Index type for OLD and NEW W_translations
   TYPE old_new 
      INTEGER(fmm_INTK) :: old, new 
   END TYPE old_new 

!------------------------------------------------------------------------------

   TYPE fmm_hilo
      REAL(fmm_REALK) :: hi, lo
   END TYPE fmm_hilo

!------------------------------------------------------------------------------

   TYPE fmm_box_id_type
      INTEGER(fmm_INTK) :: id
      REAL(fmm_REALK)   :: centre(3)
   END TYPE fmm_box_id_type

!------------------------------------------------------------------------------

END MODULE fmm_global_types


